<template>
  <div class="currentBox">
    <!-- 头部 -->
    <div class="topPart">
      <div class="backBtn" @click="back()"> <svg-icon class-name="back-icon" icon-class="back" /><span>返回</span></div>
      <div class="topMainTitle">课堂数据分析</div>

      <div class="topRight">
        <span style="margin-right:20px">采样间隔：{{ classInfo.interval }}秒</span>
        <span style="margin-right:20px">开始时间：{{ classInfo.startTime }}</span>
        <span>结束时间：{{ classInfo.endTime }}</span>
      </div>
    </div>
    <!-- 课程信息 -->
    <!-- <div class="classBtnLine">
      <div class="classInfoBtn">班级：高二4班</div>
      <div class="classInfoBtn">教师：王老师</div>
      <div class="classInfoBtn">课程：语文</div>
      <div class="classInfoBtn">学生：{{ total }}人</div>
    </div> -->
    <div class="classBtnLine">
      <div class="classInfoBtn">任务名称：{{ classInfo.name }}</div>
      <div class="classInfoBtn">应到人员：{{ classInfo.users }}人</div>
      <PdfExport v-if="showPdf" :pdf-all-data="pdfAllData" />
    </div>

    <div class="mainbody">
      <div class="mainbody-left">
        <!-- 主要模块(视频+数据) -->
        <div class="mainPart">
          <div class="videoPart-out">
            <div class="videoPart">
              <div class="videoPart-tab">
                <button :class="{ active: vedioTab === 'teacher' }" @click="switchTab('teacher')">老师</button>
                <button :class="{ active: vedioTab === 'student' }" @click="switchTab('student')">学生</button>
              </div>
              <video v-if="isVideoReady" ref="videoPlayer" width="100%" height="100%" controls muted autoplay />
            </div>
            <div class="videoTimeList" v-if=" timeLine && timeLine.length > 0">
              <div class="videoTimeList-line" v-for="(item) in timeLine" :key="item.time" @click="palyVideoByTime(item.seconds)">
                <div class="videoTimeList-dot"></div>
                <div class="videoTimeList-time">{{ item.time }}</div>
                <div class="videoTimeList-text">{{ item && item.type ? getTypeName(item.type) : '未知类型' }}</div>
              </div>
            </div>

          </div>



          <div class="dataBox" style="flex:1">
            <div class="dataBoxTitle"> <img src="../../assets/titleIcon.png" alt="">行为占比统计</div>
            <div class="innerActs">
              <div class="innerLine" style="border-bottom:1px solid #2655a7">
                <!-- <div class="roleTitle">老师</div> -->
                <div class="actionLine">
                  <div class="actionItem">
                    <div>教师讲授</div>
                    <div>{{ getPercentage(t0) }}</div>
                  </div>
                  <div class="actionItem actionBg">
                    <div>指导学生</div>
                    <div>{{ getPercentage(t1) }}</div>
                  </div>
                  <div class="actionItem">
                    <div>老师巡视</div>
                    <div>{{ getPercentage(t2) }}</div>
                  </div>
                </div>
              </div>
              <div class="innerLine">
                <!-- <div class="roleTitle">学生</div> -->
                <div class="actionLine">
                  <div class="actionItem actionBg">
                    <div>学生汇报</div>
                    <div>{{ getPercentage(s0) }}</div>
                  </div>
                  <div class="actionItem">
                    <div>师生互动</div>
                    <div>{{ getPercentage(s1) }}</div>
                  </div>
                  <div class="actionItem actionBg">
                    <div>生生互动</div>
                    <div>{{ getPercentage(s2) }}</div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div class="dataBox dataBoxWidth2 " style="padding-bottom:10px; ">
            <div class="dataBoxTitle"> <img src="../../assets/titleIcon.png" alt="">教学行为分析</div>
            <fuctionLine v-if="showFunction1" :action-data="action1" />
            <fuctionLine v-if="showFunction2" :action-data="action2" />
            <fuctionLine v-if="showFunction3" :action-data="action3" />
            <fuctionLine v-if="showFunction4" :action-data="action4" />
            <fuctionLine v-if="showFunction5" :action-data="action5" />
            <fuctionLine v-if="showFunction6" :action-data="action6" />

          </div>
        </div>
        <!-- 数据分析 -->
        <div class="analysisPart">
          <div class="dataBox dataBoxWidth2" style="margin-left:0px;">
            <div class="dataBoxTitle"> <img src="../../assets/titleIcon.png" alt="">课堂时间分配</div>
            <div class="dataText">合理调整教学环节的时间分配，精讲精练，达到课堂结构的最优化，课堂效果的最佳化。</div>
            <halfCircle v-if="showPercent" :percent-data="percentData" />
          </div>
          <div class="dataBox dataBoxWidth2" style="position: relative;">
            <div class="gridTitleVertical">学生行为时间(单位:分)</div>
            <div class="dataBoxTitle"> <img src="../../assets/titleIcon.png" alt="">S-T教学行为分析</div>
            <lineChart v-if="showST" :st-data="stData" :grid-set="gridSet" />
            <div class="gridTitle">老师行为时间(单位:分)</div>
          </div>
          <div class="dataBox dataBoxWidth2">
            <div class="dataBoxTitle"> <img src="../../assets/titleIcon.png" alt="">Rt-Ch图</div>
            <div class="dataBoxTwo">
              <div class="dataBoxTwo-title">Ch</div>
              <div class="dataBoxTwo-left">
                <triangleLine v-if="showRtCh" :rt-ch-data="RtChData" />
                <div class="dataBoxTwo-title2">Rt</div>
              </div>
              <div class="dataBoxTwo-rigth">
                <div class="dataBoxTwo-Tip">互动类型<span>{{ reactType }}</span></div>
                <div class="dataBoxTwo-Tip2">互动转换指数<span>{{ typeof reactRate === 'number' ? reactRate.toFixed(2) : '--' }}%</span></div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="mainbody-right" :class="{ 'mainbody-right2': !this.$VOICE }">
        <div class="dataBoxTitle"> <img src="../../assets/titleIcon.png" alt="">语音分析</div>

        <div class="voiceBox" style="margin-top:40px">
          <div style="flex: 1;width: 100%;">
            <cloudBall
              ref="outside1"
              :words="modalWords1"
              :width="178"
              :height="120"
              :some-other-data="{ info: '数据A' }"
              @component-ready="() => onCloudReady('outside1')"
            />
          </div>
          <div class="voiceBox-btn" @click="openLanguageBox()">
            语言分析
          </div>
        </div>

        <div class="voiceBox">
          <span>平均语速</span>
          <h1 style="color: #ffe35e;">{{ speakingSpeed }}</h1>
          <span style="color: #ffe35e;">字/分</span>
          <div class="voiceBox-btn" @click="speedBox = true">
            语速分析
          </div>
        </div>

        <!-- <div class="voiceBox">
          <span>提问比例</span>
          <h1 style="color: #aceb59;">40%</h1>
          <div class="voiceBox-btn" @click="questionBox = true">
            课堂提问
          </div>
        </div> -->

        <div class="voiceBox" style="margin-bottom: 30px;">
          <span>有效录制</span>
          <h1 style="color: #2fe4ff;">{{ totalMinutes }}</h1>
          <span style="color: #2fe4ff;">min</span>
          <div class="voiceBox-btn" @click="openVoiceText()">
            语音实录
          </div>
        </div>

        <!-- 语音分析的弹窗 -->
        <el-dialog title="语音分析" :visible.sync="languageBox" class="voicePop">
          <div class="voicePop-tabLine">
            <div class="voicePop-tabLine-btn" :class="{ btnActive: activeTab === 'tab1' }" @click="activeTab = 'tab1'">
              高频词</div>
            <div class="voicePop-tabLine-btn" :class="{ btnActive: activeTab === 'tab2' }" @click="activeTab = 'tab2'">
              关键词</div>
            <!-- <div class="voicePop-tabLine-btn" :class="{ btnActive : activeTab === 'tab3' }" @click="activeTab = 'tab3'">语气词</div> -->
          </div>

          <div v-show="activeTab === 'tab1'" class="voicePop-textLine">
            <div v-if="modalWords1.length > 0">
              本次课堂高频词前10个，<span>“{{ modalWords1[0].text }}”</span>出现频率最高，共<span>{{ modalWords1[0].count }}次</span>。
            </div>
            <div v-else>
              暂无高频词
            </div>

          </div>

          <div v-show="activeTab === 'tab2'" class="voicePop-textLine">
            <div v-if="modalWords2.length > 0">
              本次课堂关键词中，<span>“{{ modalWords2[0].text }}”</span>出现频率最高，共<span>{{ modalWords2[0].count }}次</span>。
            </div>
            <div v-else>暂无关键词</div>
          </div>

          <!-- <div class="voicePop-textLine" v-show="activeTab === 'tab3'">
            本次课堂语气词共<span>32个</span>，“sss”出现频率最高，共<span>50次</span>。
          </div> -->

          <!-- tab1 -->
          <div v-show="activeTab === 'tab1'" class="voicePop-inBox">
            <div class="voicePop-inBox-ball">
              <cloudBall
                ref="modal1"
                :words="modalWords1"
                :width="300"
                :height="400"
                @component-ready="() => onCloudReady('modal1')"
              />
            </div>
            <div class="voicePop-inBox-table">
              <el-table :data="sortedModalWords1" style="width: 100%">
                <el-table-column label="序号" align="center" width="100">
                  <template slot-scope="scope">
                    {{ scope.$index + 1 }}
                  </template>
                </el-table-column>
                <el-table-column prop="text" label="词语" align="center" />
                <el-table-column prop="count" label="频次" align="center" />
              </el-table>
            </div>
          </div>
          <!-- tab2 -->
          <div v-show="activeTab === 'tab2'" class="voicePop-inBox">
            <div class="voicePop-inBox-ball">
              <cloudBall
                ref="modal2"
                :words="modalWords2"
                :width="300"
                :height="400"
                @component-ready="() => onCloudReady('modal2')"
              />
            </div>
            <div class="voicePop-inBox-table">
              <el-table :data="sortedModalWords2" style="width: 100%">
                <el-table-column label="序号" align="center" width="100">
                  <template slot-scope="scope">
                    {{ scope.$index + 1 }}
                  </template>
                </el-table-column>
                <el-table-column prop="text" label="词语" align="center" />
                <el-table-column prop="count" label="频次" align="center" />
              </el-table>
            </div>
          </div>
          <!-- tab3 -->
          <!-- <div class="voicePop-inBox" v-show="activeTab === 'tab3'">
            <div class="voicePop-inBox-ball">
              <cloudBall
                :words="modalWords3"
                :width="300"
                :height="400"
                @component-ready="() => onCloudReady('modal3')"
                ref="modal3"
              />
            </div>
            <div class="voicePop-inBox-table">
              <el-table :data="sortedModalWords3" style="width: 100%" >
                <el-table-column label="序号" align="center" width="100" >
                  <template slot-scope="scope">
                    {{ scope.$index + 1 }}
                  </template>
                </el-table-column>
                <el-table-column prop="text" label="词语"  align="center" />
                <el-table-column prop="count" label="频次" align="center" />
              </el-table>
            </div>
          </div> -->

        </el-dialog>

        <!-- 语速分析的弹窗 -->
        <el-dialog title="语速分析" :visible.sync="speedBox" class="voicePop">
          <div class="voicePop-textLine">
            教师语速是否合理科学直接影响教学效果，标准语速建议为<span>200-250字/分钟</span>；语速过快会导致学生没有足够的时间来思考、吸收、记忆；反之会导致学生的精力涣散。
          </div>

          <div class="voicePop-inBox2">
            <div class="voiceBox voicePop-inBox2-left ">
              <span>平均语速</span>
              <h1 style="color: #ffe35e;">{{ speakingSpeed }}</h1>
              <span style="color: #ffe35e;">字/分</span>
            </div>
            <div class="voicePop-inBox2-right">
              <div style="color: #b1c7f3; font-size: 16px;margin-bottom: 20px;">最长发言<span style="color: #cead1b;">{{
                maxSpeakingTime }}s</span></div>
              <div style="color: #fff;line-height: 28px;">{{ maxSpeakingText }}</div>
            </div>
          </div>
        </el-dialog>

        <!-- 课堂问答的弹窗 -->
        <el-dialog title="课堂问答" :visible.sync="questionBox" class="voicePop">
          <div class="voicePop-textLine">
            本节课一共提问<span>32次</span>，其中基础认知问题共<span>10次</span>，占<span>10%</span>；高级认知问题共<span>8次</span>，占比<span>8%</span>；无认知水平问题共<span>12次</span>，占比<span>12%</span>。从数据中可以看出本节课提问比较侧重评价型问题，记忆型的问题提问较少。另外，在这些问题中，3个为何问题，2个如何问题，4个若何问题，1个是何问题，0个其他问题。
          </div>
          <div class="voicePop-inBox3">
            <div class="voicePop-inBox3-in ">
              <RadarChart
                :indicator-data="indicatorData1"
                :series-data="seriesData1"
                data-color="#ffc340"
                area-color="rgba(255,195,64,0.4)"
              />
            </div>
            <div class="voicePop-inBox3-in ">
              <RadarChart
                :indicator-data="indicatorData2"
                :series-data="seriesData2"
                data-color="#86d520"
                area-color="rgba(134,213,32,0.4)"
              />
            </div>
          </div>
          <div class="voicePop-inBox4">
            <div class="voicePop-inBox4-in" style="color:#ffc340 ;">布鲁姆教育目标分类法</div>
            <div class="voicePop-inBox4-in" style="color:#86d520">麦卡锡4MAT模式</div>
          </div>
        </el-dialog>

        <!-- 语音实录的弹窗 -->
        <el-dialog title="语音实录" :visible.sync="recordBox" class="voicePop">

          <div class="voicePop-inBox5">
            <div class="voicePop-inBox5-top">
              <el-input v-model="input00" placeholder="输入关键字检索" />
              <span>共查询到 {{ filteredSpeakData.length }}条结果</span>
              <div class="voicePop-inBox5-topBtn" @click="downloadTxt">下载</div>
            </div>

            <div class="voicePop-inBox5-list">
              <div v-for="(item) in filteredSpeakData" :key="item.time" class="voicePop-inBox5-listOne">
                <div style="width:160px">{{ item.time }}</div>
                <div class="voicePop-inBox5-txt">
                  <div v-if="item.editMode">
                    <el-input v-model="item.text" type="textarea" :rows="2" size="small" />
                    <div class="voicePop-inBox5-inBtn">
                      <div @click="saveEdit(item)">确定</div>
                      <div @click="cancelEdit(item)">取消</div>
                    </div>
                  </div>
                  <span v-else>{{ item.text }}</span>
                </div>
                <div v-if="!item.editMode" class="voicePop-inBox5-btn">
                  <i class="el-icon-edit" @click="startEdit(item)" />
                  <i class="el-icon-delete" @click="deleteLine(item)" />
                </div>
              </div>
            </div>

            <div class="voicePop-inBox5-submitLine">
              <div class="voicePop-inBox5-submitBtn" @click="editVoiceText">提交所有修改</div>
              提示：所有修改和删除都需要提交
            </div>

          </div>
        </el-dialog>

      </div>
    </div>

  </div>
</template>

<script>
import halfCircle from './charts/halfCircle.vue'
import RadarChart from './charts/RadarChart.vue'
import lineChart from './charts/lineChart.vue'
import fuctionLine from './charts/fuctionLine.vue'
import triangleLine from './charts/triangleLine.vue'
import cloudBall from './charts/cloudBall.vue'
import Hls from 'hls.js'
import dayjs from 'dayjs'
// pdf下载
import PdfExport from './PdfExport.vue'

// 接口
import { getDataST, getDataRtCh, getDataPfCh, getTaskDataById, getVoiceData, getVoiceText, updateVoiceText, getVideoTime } from '@/api/main'

export default {
  name: 'ClassAnalysis',
  components: { lineChart, halfCircle, fuctionLine, triangleLine, cloudBall, RadarChart, PdfExport },
  data() {
    return {
      hls: null,
      isVideoReady: false,
      vedioTab: 'teacher', // 添加当前激活的标签状态
      isSwitching: false, // 添加切换状态标志
      id: null,
      studentTimeLine: [],
      teacherTimeLine: [],
      timeLine:[],
      classInfo: {
        name: '',
        users: null,
        startTime: null,
        endTime: null,
        interval: null
      },
      total: 45,
      imgsrc: require('../../assets/img001.png'),
      listenNum: 30,
      writenNum: 30,
      replyNum: 40,
      sleepNum: 10,
      reactNum: 20,
      // 没有数据时图表不显示，防止加载完成时还没获得数据
      showST: false,
      showRtCh: false,
      length: null,
      gridSet: {
        max: null,
        interval: null
      },
      showFunction1: false,
      showFunction2: false,
      showFunction3: false,
      showFunction4: false,
      showFunction5: false,
      showFunction6: false,
      // 传递给图表的数据
      action1: {},
      action2: {},
      action3: {},
      action4: {},
      action5: {},
      action6: {},
      action7: {//
        categories: ['xxxx'], // name
        itemColor: '#329932', // 颜色
        data: [// 数据
          ['1', 1],
          ['2', 0],
          ['3', 0],
          ['4', 0],
          ['5', 0],
          ['6', 0],
          ['7', 0],
          ['8', 0],
          ['9', 0],
          ['10', 1],
          ['11', 1],
          ['12', 1],
          ['13', 1],
          ['14', 1],
          ['15', 1],
          ['16', 1],
          ['17', 1],
          ['18', 1],
          ['19', 1],
          ['20', 1],
          ['21', 1],
          ['22', 1],
          ['23', 1],
          ['24', 1],
          ['25', 1],
          ['26', 0],
          ['27', 0],
          ['28', 0],
          ['29', 0],
          ['30', 0],
          ['31', 0],
          ['32', 0],
          ['33', 0],
          ['34', 1],
          ['35', 1],
          ['36', 0],
          ['37', 0],
          ['38', 1],
          ['39', 0],
          ['40', 1],
          ['41', 1],
          ['42', 0],
          ['43', 1],
          ['44', 1],
          ['45', 0]
        ]
      },
      percentData: {
        s_time: null,
        t_time: null,
        percent: []
      },
      showPercent: false,
      reactType: '', // 互动类型
      reactRate: 0, // 互动转换指数
      // 行为数据
      t0: null,
      t1: null,
      t2: null,
      s0: null,
      s1: null,
      s2: null,
      actionAll: 100,
      // 语音的弹窗
      languageBox: false,
      speedBox: false,
      recordBox: false,
      questionBox: false,
      activeTab: 'tab1', // 默认选中 Tab1
      wordsA: [
        { text: 'Vue', weight: 16, count: 19 },
        { text: 'JS1', weight: 18 },
        { text: 'JS34', weight: 18 },
        { text: 'JS21', weight: 18 }
      ],
      modalWords1: [], // 高频词
      modalWords2: [],
      modalWords3: [
        { text: '弹窗三', weight: 22, count: 56 },
        { text: '标签云3', weight: 19, count: 32 },
        { text: 'JdS', weight: 18, count: 19 },
        { text: 'JcvcvS', weight: 18, count: 9 },
        { text: 'JdfdS', weight: 18, count: 22 },
        { text: 'J32S', weight: 18, count: 45 },
        { text: 'J3tS', weight: 18, count: 28 },
        { text: 'JS32', weight: 18, count: 34 },
        { text: 'J4545S', weight: 18, count: 69 },
        { text: 'J4545S', weight: 18, count: 31 }
      ],
      readyStatus: {
        outside1: false,
        outside2: false,
        modal1: false,
        modal2: false,
        modal3: false
      },

      speakingSpeed: 0, // 语速
      maxSpeakingTime: 0, // 最长发言时间
      maxSpeakingText: '', // 最长发言

      indicatorData1: [
        { name: '记忆型', max: 100 },
        { name: '无认知', max: 100 },
        { name: '评价型', max: 100 },
        { name: '创新型', max: 100 },
        { name: '分析型', max: 100 },
        { name: '应用型', max: 100 },
        { name: '理解型', max: 100 }
      ],
      seriesData1: [
        {
          value: [80, 60, 80, 60, 80, 60, 50], // matches indicator order
          name: '时间分布'
        }
      ],
      indicatorData2: [
        { name: '是何', max: 100 },
        { name: '其他', max: 100 },
        { name: '若何', max: 100 },
        { name: '如何', max: 100 },
        { name: '为何', max: 100 }
      ],
      seriesData2: [
        {
          value: [80, 60, 80, 60, 80], // matches indicator order
          name: '时间分布'
        }
      ],
      tableData: [
        { id: 1, time: '00:00:03', role: '教师', content: '的幅度分割的', editMode: false },
        { id: 2, time: '00:00:03', role: '学生', content: '的幅度分割的', editMode: false }
      ],
      originalData: {}, // 用于临时存储原始数据
      input00: '',
      speakData: [],
      task_id: null,
      voiceId: null,
      totalMinutes: 0,
      showPdf: false,
      pdfAllData: {}

    }
  },
  computed: {
    Percent() {
      return (e) => {
        const num = e / this.total * 100
        return num.toFixed(2)
      }
    },
    sortedModalWords1() {
      return [...this.modalWords1].sort((a, b) => b.count - a.count)
    },
    sortedModalWords2() {
      return [...this.modalWords2].sort((a, b) => b.count - a.count)
    },
    sortedModalWords3() {
      return [...this.modalWords3].sort((a, b) => b.count - a.count)
    },
    // 语音实录的检索计算
    filteredSpeakData() {
      const keyword = this.input00.trim().toLowerCase()
      if (!keyword) return this.speakData

      return this.speakData.filter(item =>
        item.text.toLowerCase().includes(keyword)
      )
    },
  },
  watch: {
    // 监听 video 渲染完毕再播放
    isVideoReady(newVal) {
      if (newVal) {
        this.$nextTick(() => {
          this.playVideo()
        })
      }
    },
    // 监听为pdf准备的数据
    pdfAllData: {
      deep: true, // 深度监听
      handler(newData) {
        // 需要检查的所有字段
        const requiredFields = [
          'action1', 'action2', 'action3', 'action4', 'action5', 'action6',
          'percentData', 'RtChData', 'reactType', 'reactRate',
          'modalWords1', 'modalWords2', 'speakingSpeed',
          'maxSpeakingTime', 'maxSpeakingText', 'speakData',
          'className', 'actionTable'
        ];
        
        // 检查所有字段是否都已定义（非undefined和null）
        const allFieldsReady = requiredFields.every(field => {
          return newData[field] !== undefined && newData[field] !== null;
        });
        
        // 所有数据就绪，允许渲染 PdfExport
        this.showPdf = allFieldsReady;
      },
      immediate: true // 立即触发一次检查
    }
  },
  mounted() {
    this.isVideoReady = true
    this.$nextTick(() => {
      this.waitForVideoAndPlay()
    })
    // 通过id获取任务信息
    this.getInfo()
  },
  created() {
    // 获取视频的时间点
    this.getVideoTime()
    // 初始化空对象
    this.pdfAllData = {} 
    // 获取query缓存
    this.setQuery()
    // 获取st的数据
    this.getDataForST()
    // 获取rtch
    this.getDataForRtCh()
    // 获取性能
    this.getDataForPfCh()
    // 获取语音数据
    this.getVoiceData()
  },

  beforeDestroy() {
    // 销毁Hls实例
    this.destroyHls()
  },

  methods: {
    // 获取任务
    getInfo() {
      const id = this.$route.query.id
      getTaskDataById(id).then(response => {
        this.classInfo.name = response.data.task_data.name
        this.classInfo.users = response.data.task_users.length
        this.classInfo.startTime = response.data.task_data.start_time.replace('T', ' ')
        this.classInfo.endTime = response.data.task_data.end_time.replace('T', ' ')
        this.classInfo.interval = response.data.task_data.sampling_interval

        // 所有参会人员信息
        this.usersItems = response.data.task_users

        // 获取到baseTime后，进行语音文本的加载
        this.getVoiceText()

        // 合并到 pdfAllData（不覆盖已有数据）
        this.pdfAllData = Object.assign({}, this.pdfAllData, {
          className: response.data.task_data.name || ''
        })
      })
    },
    // 设置缓存
    setQuery() {
      const params = this.$route.query
      //  console.log('--------params',params)

      if (Object.keys(params).length === 0) {
        const savedParams = JSON.parse(localStorage.getItem('queryParams'))
        if (savedParams) {
          this.$router.replace({ query: savedParams })
        }
      } else {
        localStorage.setItem('queryParams', JSON.stringify(params))
      }
    },
    back() {
      // this.$router.back()
      this.$router.push({ path: '/classList' })
    },

    waitForVideoAndPlay(retry = 10) {
      const video = this.$refs.videoPlayer
      if (video) {
        this.playVideo(video)
      } else if (retry > 0) {
        // 每隔100ms再试一次，最多试10次（1秒）
        setTimeout(() => {
          this.waitForVideoAndPlay(retry - 1)
        }, 100)
      } else {
        console.error('video 元素始终未挂载')
      }
    },
    // 获取时间点
    getVideoTime(){
      const id = this.$route.query.id
      getVideoTime(id).then(response => {

        // 工具函数：用dayjs将秒数转为 hh:mm:ss 格式
        const formatSecToHms = (seconds) => {
          // 1. 把秒数转为数字（避免字符串格式问题）
          const secNum = parseInt(seconds, 10)
          // 2. 用dayjs设置秒数（会自动处理分、时进位），再格式化为两位数的时分秒
          return dayjs().startOf('day').second(secNum).format('HH:mm:ss')
        }

        // 转换s数组并赋值给this.studentTimeLine
        this.studentTimeLine = response.data.s.map(item => ({
            time: formatSecToHms(item[0]),
            type: item[1],
            seconds: item[0]
        }))

        // 转换t数组并赋值给this.teacherTimeLine
        this.teacherTimeLine = response.data.t.map(item => ({
            time: formatSecToHms(item[0]),
            type: item[1],
            seconds: item[0]
        }))

        // 总时间轴
        this.timeLine =  this.studentTimeLine.concat(this.teacherTimeLine);

        // 按 time 字段排序
        this.timeLine.sort((a, b) => {
          // 直接用原始秒数（item[0]）排序，和 time 字段是一一对应的（因为 time 由它转换而来）
          return parseInt(a.seconds, 10) - parseInt(b.seconds, 10);
        });

      })
    },
    // 获取St数据
    getDataForST() {
      const id = this.$route.query.id
      getDataST(id).then(response => {
        this.stData = response.data.st_data
        // this.length=response.data.duration
        this.setChartGrid(response.data.duration)
        this.showST = true
        // 课堂百分比
        const s_percent = Number((response.data.s_percent * 100).toFixed(1))
        const t_percent = 100 - s_percent
        const sTime = Number((response.data.duration / 60 * s_percent / 100).toFixed(0))
        const tTime = Number((response.data.duration / 60 * t_percent / 100).toFixed(0))
        this.percentData = {
          s_time: sTime,
          t_time: tTime,
          s_percent: s_percent,
          t_percent: t_percent
        }
        this.showPercent = true

        // 合并到 pdfAllData（不覆盖已有数据）
        this.pdfAllData = Object.assign({}, this.pdfAllData, {
          percentData: this.percentData,
          stData: this.stData
        })
      })
    },
    // ST图表样式间隔计算
    setChartGrid(length) {
      if (length <= 900) {
        this.gridSet.max = 900
        this.gridSet.interval = 60
      } else if (length > 900 && length <= 1800) {
        this.gridSet.max = 1800
        this.gridSet.interval = 120
      } else if (length > 1800 && length <= 2700) {
        this.gridSet.max = 2700
        this.gridSet.interval = 180
      } else if (length > 2700 && length <= 3600) {
        this.gridSet.max = 3600
        this.gridSet.interval = 300
      } else {
        const roundNum = Math.ceil(length / 50)
        this.gridSet.max = roundNum * 50
        this.gridSet.interval = (roundNum * 50) / 10
      }
      this.pdfAllData = Object.assign({}, this.pdfAllData, {
        gridSet: this.gridSet
      })
    },

    // 获取性能数据
    getDataForPfCh() {
      const id = this.$route.query.id
      getDataPfCh(id).then(response => {
        console.log('------------response',response)
        //
        this.action1 = {
          categories: ['教师讲授'], // name
          itemColor: '#993232', // 颜色
          data: response.data.t0
        }
        this.showFunction1 = true
        //
        this.action2 = {
          categories: ['指导学生'], // name
          itemColor: '#2d90f9', // 颜色
          data: response.data.t1
        }
        this.showFunction2 = true
        //
        this.action3 = {
          categories: ['老师巡视'], // name
          itemColor: '#7d9932', // 颜色
          data: response.data.t2
        }
        this.showFunction3 = true
        //
        this.action4 = {
          categories: ['学生汇报'], // name
          itemColor: '#24b8c9', // 颜色
          data: response.data.s0
        }
        this.showFunction4 = true
        //
        this.action5 = {
          categories: ['师生互动'], // name
          itemColor: '#c84ae3', // 颜色
          data: response.data.s1
        }
        this.showFunction5 = true
        //
        this.action6 = {
          categories: ['生生互动'], // name
          itemColor: '#e0c92e', // 颜色
          data: response.data.s2
        }
        this.showFunction6 = true
        // 行为数据
        this.t0 = response.data.t0_count
        this.t1 = response.data.t1_count
        this.t2 = response.data.t2_count
        this.s0 = response.data.s0_count
        this.s1 = response.data.s1_count
        this.s2 = response.data.s2_count
        this.actionAll =  this.t0 + this.t1 + this.t2 + this.s0 + this.s1 + this.s2;

        // 初始化 pdfAllData（如果尚未初始化）
        if (!this.pdfAllData) {
          this.pdfAllData = {}
        }

        // 合并 action 数据
        this.pdfAllData = Object.assign({}, this.pdfAllData, {
          action1: { categories: ['教师讲授'], itemColor: '#993232', data: response.data.t0 },
          action2: { categories: ['指导学生'], itemColor: '#2d90f9', data: response.data.t1 },
          action3: { categories: ['老师巡视'], itemColor: '#7d9932', data: response.data.t2 },
          action4: { categories: ['学生汇报'], itemColor: '#24b8c9', data: response.data.s0 },
          action5: { categories: ['师生互动'], itemColor: '#c84ae3', data: response.data.s1 },
          action6: { categories: ['生生互动'], itemColor: '#e0c92e', data: response.data.s2 },
          actionTable: [this.t0, this.t1, this.t2, this.s0, this.s1, this.s2]
        })
      })
    },
    // 通用百分比计算函数：参数为需要计算的数值（如 this.t0）
    getPercentage(value) {
      // 处理总数为0的情况，返回0%避免NaN
      if (this.actionAll === 0) {
        return '0%';
      }
      // 计算百分比（保留两位小数）
      const percentage = (value / this.actionAll) * 100;
      return percentage.toFixed(2) + '%';
    },

    // 获取rtch数据
    getDataForRtCh() {
      const id = this.$route.query.id
      getDataRtCh(id).then(response => {
        this.showRtCh = true
        this.RtChData = [[response.data[0], response.data[1]]]
        console.log('--------------RtChData', this.RtChData)
        // 互动类型
        const x = response.data[0]
        const y = response.data[1]
        if (x > 0 && x <= 0.3 && y > 0 && y <= 0.6) {
          this.reactType = '练习型'
        } else if (x > 0.3 && x <= 0.7 && y > 0 && y <= 0.4) {
          this.reactType = '混合型'
        } else if (x > 0.7 && y <= 1 && y >= 0 && y <= 0.6) {
          this.reactType = '讲授型'
        } else {
          this.reactType = '对话型'
        }
        // 互动转换指数
        this.reactRate = y * 100

        // 加到pdf数据里
        this.pdfAllData = Object.assign({}, this.pdfAllData, {
          RtChData: this.RtChData,
          reactType: this.reactType,
          reactRate: this.reactRate
        })
      })
    },

    // 词语处理---取前十、排序、字体权重
    formatTopWords(originalData) {
      const top10 = originalData
        .sort((a, b) => b.count - a.count)
        .slice(0, 10)

      return top10.map((item, index) => {
        let weight = 14
        if (index === 0) {
          weight = 20
        } else if (index === 1 || index === 2) {
          weight = 18
        } else if (index >= 3 && index <= 5) {
          weight = 16
        }

        return {
          text: item.word,
          count: item.count,
          weight
        }
      })
    },

    // 获取语音数据
    getVoiceData() {
      const id = this.$route.query.id
      getVoiceData(id).then(res => {
        if (res.code === 20000) {
          this.speakingSpeed = Math.round(res.data.average_speaking_speed)
          this.maxSpeakingTime = Math.round(res.data.maximum_speaking_time)
          this.maxSpeakingText = res.data.maximum_speaking_time_text

          // 高频词处理
          this.modalWords1 = this.formatTopWords(res.data.high_frequency_words)
          // 关键字处理
          this.modalWords2 = this.formatTopWords(res.data.keywords)

          // 加到pdf数据里
          this.pdfAllData = Object.assign({}, this.pdfAllData, {
            modalWords1: this.modalWords1 || '',
            modalWords2: this.modalWords2 || '',
            speakingSpeed: this.speakingSpeed || '',
            maxSpeakingTime: this.maxSpeakingTime || '',
            maxSpeakingText: this.maxSpeakingText || '',
          })
        }
      })
    },
    // 打开语音文本弹窗
    openVoiceText() {
      this.recordBox = true
    },

    // 获取语音文本
    getVoiceText() {
      const id = this.$route.query.id
      getVoiceText(id).then(res => {
        if (res.code === 20000) {
          this.voiceId = res.data.sections.id
          this.task_id = res.data.sections.task_id
          const baseTime = dayjs(this.classInfo.startTime)
          this.speakData = res.data.sections.text.map(item => {
            const time = baseTime.add(item.start, 'millisecond').format('YYYY-MM-DD HH:mm:ss')
            return {
              end: item.end,
              start: item.start,
              time: time,
              text: item.text,
              editMode: false
            }
          })
          this.totalMinutes = this.getTotalDurationInMinutes(this.speakData)
          // 加到pdf数据里
          this.pdfAllData = Object.assign({}, this.pdfAllData, {
            speakData: this.speakData  || [] 
          })
        }
      })
    },
    // 计算总时长
    getTotalDurationInMinutes(data) {
      if (!data || data.length === 0) {
        return 0
      }

      let duration = 0

      if (data.length === 1) {
        duration = data[0].end - data[0].start
      } else {
        duration = data[data.length - 1].end - data[0].start
      }

      const minutes = Math.floor(duration / 1000 / 60)
      return minutes
    },
    // 开始编辑
    startEdit(row) {
      this.originalData = { ...row } // 深拷贝原始数据
      row.editMode = true
    },
    // 保存编辑
    saveEdit(row) {
      row.editMode = false
      // 这里可以添加API保存逻辑
      console.log('保存的row:', row)
      console.log('整个:', this.speakData)
    },
    // 取消编辑（可选）
    cancelEdit(row) {
      if (this.originalData) {
        Object.assign(row, this.originalData)
      } else {
        console.warn('originalData 未定义')
      }
      row.editMode = false
    },
    // 删除
    deleteLine(row) {
      const index = this.speakData.findIndex(item => item === row)
      if (index !== -1) {
        this.speakData.splice(index, 1)
      }
    },

    // 修改语音文本
    editVoiceText() {
      console.log(this.voiceId, this.task_id, this.speakData)
      const cleanSpeakData = this.speakData.map(item => ({
        start: item.start,
        end: item.end,
        text: item.text
      }))

      const data = {
        id: this.voiceId,
        task_id: this.task_id,
        text: JSON.stringify(cleanSpeakData)
      }
      // 修改
      updateVoiceText(data).then(response => {
        if (response.code === 20000) {
          this.speakData = []
          this.$message({
            message: '提交成功！',
            type: 'success',
            duration: 2000
          })
          this.getVoiceText()
        } else {
          this.msgSuccess(response.message)
        }
      })
    },

    // 云球的相关方法
    openLanguageBox() {
      this.readyStatus.modal1 = false
      this.readyStatus.modal2 = false
      this.readyStatus.modal3 = false
      this.languageBox = true
    },
    onCloudReady(refName) {
      this.readyStatus[refName] = true
      console.log(`${refName} 标签云组件已就绪`)
    },
    refreshModalClouds() {
      this.$nextTick(() => {
        ['modal1', 'modal2', 'modal3'].forEach(refName => {
          const comp = this.$refs[refName]
          if (comp && typeof comp.reInit === 'function') {
            comp.reInit()
          }
        })
      })
    },

    // 下载文本
    downloadTxt() {
      if (!this.speakData || !this.speakData.length) {
        this.$message.warning('暂无数据可下载')
        return
      }

      // 1. 拼接文本：每行是 "时间\t文字"
      const content = this.speakData.map(item => {
        return `${item.time}    ${item.text}`
      }).join('\n')

      // 2. 创建 Blob 对象
      const blob = new Blob([content], { type: 'text/plain;charset=utf-8' })

      // 3. 创建下载链接并触发下载
      const link = document.createElement('a')
      link.href = URL.createObjectURL(blob)
      link.download = '语音实录.txt'
      link.click()

      // 4. 释放资源
      URL.revokeObjectURL(link.href)
    },

    // 以下是视频播放的相关代码
    // 切换标签
    async switchTab(tab) {
      console.log('点击按钮', tab)
      if (this.vedioTab === tab || this.isSwitching) {
        return
      }

      this.isSwitching = true
      this.vedioTab = tab

      try {
        await this.switchVideo()
      } catch (error) {
        console.error('切换视频失败:', error)
      } finally {
        this.isSwitching = false
      }
    },
    // 切换视频
    async switchVideo() {
      const videoElement = this.$refs.videoPlayer
      if (!videoElement) {
        return
      }

      // 暂停当前播放
      if (!videoElement.paused) {
        videoElement.pause()
      }

      // 等待一小段时间让播放器稳定
      await new Promise(resolve => setTimeout(resolve, 100))

      // 重新加载视频
      await this.playVideo(videoElement)
    },

    // 新增：点击时间点跳转播放
    palyVideoByTime(timeStr) {
      const videoElement = this.$refs.videoPlayer;
      if (!videoElement) {
        console.error('视频元素不存在，无法跳转');
        return;
      }

      videoElement.currentTime = timeStr; // 设置视频当前播放时间
      videoElement.play().catch(error => {
        console.warn('跳转后播放失败:', error);
      });
    },
    // 行为活动名称
    // 接收type参数，返回对应的中文名称
    getTypeName(type) {
      const typeMap = {
        'S_0': '学生汇报',
        'S_1': '师生互动',
        'S_2': '生生互动',
        'T_1': '指导学生',
        'T_2': '老师巡视'
      };

      // 第一层：校验type是否有效（排除undefined/null/空字符串）
      if (!type) return '未知类型';
      // 第二层：校验type是否在映射表中，不在则返回“未定义类型+原始值”（便于调试）
      return typeMap[type] || `未定义类型(${type})`;
    },


    // 视频播放
    playVideo() {
      // 不传入videoElement参数，每次都重新获取
      const videoElement = this.$refs.videoPlayer
      if (!videoElement) {
        console.error('视频元素不存在')
        return
      }

      const id = this.$route.query.id
      if (!id) {
        console.error('播放视频失败：id 为空')
        return
      }

      const urlS = this.$VIDEO_URL + '/' + id + '/' + id + '_s.m3u8' // 学生地址
      const urlT = this.$VIDEO_URL + '/' + id + '/' + id + '_t.m3u8' // 老师地址

      // 根据当前激活的标签获取对应的视频URL
      const url = this.vedioTab === 'student' ? urlS : urlT
      console.log('----------地址', url)

      if (!url) {
        console.error('视频URL为空')
        return
      }

      // 销毁之前的HLS实例
      this.destroyHls()

      if (Hls.isSupported()) {
        this.hls = new Hls()
        this.hls.loadSource(url)
        this.hls.attachMedia(videoElement)

        this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
          // 在回调中重新获取video元素确保存在
          const currentVideo = this.$refs.videoPlayer
          if (currentVideo) {
            // 新增：监听元数据加载完成，确保可跳转
            currentVideo.addEventListener('loadedmetadata', () => {
              currentVideo.play().catch(error => {
                console.warn('自动播放被阻止:', error)
              })
            }, { once: true }); // 只监听一次，避免重复触发
          }
        })
      } else if (videoElement.canPlayType('application/vnd.apple.mpegurl')) {
        videoElement.src = url
        videoElement.addEventListener('loadedmetadata', () => {
          const currentVideo = this.$refs.videoPlayer
          if (currentVideo) {
            currentVideo.play().catch(error => {
              console.warn('自动播放被阻止:', error)
            })
          }
        }, { once: true } // 补充 once 选项
      )
      } else {
        console.error('当前浏览器不支持 HLS 播放')
      }
    },
    // 销毁HLS实例
    destroyHls() {
      if (this.hls) {
        this.hls.destroy()
        this.hls = null
      }
    }
  }
}
</script>

<style scoped>
.mainbody-right2{
  display: none;
}
/* 适用于 Chrome、Edge、Safari */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: #22488f;
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: #2e58a7;
}

::-webkit-scrollbar-button {
  display: none;
}

/* 适用于 Firefox */
html {
  scrollbar-width: thin;
  scrollbar-color: #888 transparent;
}
</style>
